#pragma once

#include <stdio.h>

namespace strategy {
    
/// @brief 抽象策略类, 定义了一个公共接口，各种不同的算法以不同的方式实现这个接口，环境角色使用这个接口调用不同的算法
class AbstractStrategy {
public:
    virtual ~AbstractStrategy() {}
    virtual void StrategyMethod() = 0;
};

/// @brief 具体策略类, 实现了抽象策略定义的接口，提供具体的算法实现
class ConcreteStrategyA : public AbstractStrategy {
public:
    virtual void StrategyMethod() {
        printf("this is ConcreteStrategyA::StrategyMethod!\n");
    }
};
class ConcreteStrategyB : public AbstractStrategy {
public:
    virtual void StrategyMethod() {
        printf("this is ConcreteStrategyB::StrategyMethod!\n");
    }
};

/// @brief 环境类, 持有一个策略类的引用，最终给客户端调用
class Context {
public:
    void SetStrategy(AbstractStrategy* strategy) {
        strategy_ = strategy;
    }
    void StrategyMethod() {
        if (strategy_) strategy_->StrategyMethod();
    }

private:
    AbstractStrategy* strategy_ = nullptr;
};

} // namespace strategy

void Test_14_strategy_impl_1() {
    printf("-------------------- %s --------------------\n", __FUNCTION__);
    strategy::AbstractStrategy* ptr_strategy_A = new strategy::ConcreteStrategyA();
    strategy::AbstractStrategy* ptr_strategy_B = new strategy::ConcreteStrategyB();

    strategy::Context env_;
    env_.SetStrategy(ptr_strategy_A);
    env_.StrategyMethod();

    env_.SetStrategy(ptr_strategy_B);
    env_.StrategyMethod();

    delete ptr_strategy_A;
    delete ptr_strategy_B;
}

// -------------------- Test_14_strategy_impl_1 --------------------
// this is ConcreteStrategyA::StrategyMethod!
// this is ConcreteStrategyB::StrategyMethod!